#include "OperatorHandler.h"
#include "..\..\Common\StringHelper.h"
#include "..\..\Common\AssertHelper.h"

using namespace std;

namespace CExpression
{
	bool OperatorHandler::ParseCore(ParseContext &context)
	{
		bool ret = false;
		shared_ptr<ExpressionToken> token=context.Tokens()[context.CurrentTokenIndex()];
        if (StringHelper::IsOperatorChar(token->Token[0]))
        {
            this->ParseOperator(token, context);
            ret = true;
        }
        return ret;
	}

	void OperatorHandler::ParseOperator(shared_ptr<ExpressionToken> token,ParseContext &context)
	{
		//ExpressionString op2=token->Token;
		if(token->Token==TEXT("-")||token->Token==TEXT("+"))
		{
			if(context.CurrentTokenIndex()>0)
			{
				shared_ptr<ExpressionToken> prevTolen=context.Tokens()[context.CurrentTokenIndex()-1];
				ExpressionChar prevChar=prevTolen->Token[prevTolen->Token.size()-1];
				if(!(prevChar!=TEXT('(')&&prevChar!=TEXT(',')&&!StringHelper::IsNoneUnitaryOperatorChar(prevChar)))
				{
					token->Token=TEXT("Unitary")+token->Token;
				}
			}
			else
			{
				token->Token=TEXT("Unitary")+token->Token;
			}
		}
		if(context.OperatorStack().size()>0)
		{
			shared_ptr<ExpressionToken> tempToken=context.OperatorStack().top();
			context.OperatorStack().pop();
			while(true)
			{
				//OutputDebugString(ParseContext::operatorPriority!=0?TEXT("Test Constructed."):TEXT("Test NoConstructed."));
				map<ExpressionString,int>::iterator iter1=ParseContext::operatorPriority->find(tempToken->Token);
				map<ExpressionString,int>::iterator iter2=ParseContext::operatorPriority->find(token->Token);
				if(StringHelper::EndWith(tempToken->Token,TEXT("(")))
				{
					context.OperatorStack().push(tempToken);
					context.OperatorStack().push(token);
					break;
				}
				else if(iter1!=ParseContext::operatorPriority->end()&&iter2!=ParseContext::operatorPriority->end())
				{
					int priority1 = iter1->second;
                    int priority2 = iter2->second;
					if(priority2 > priority1)
					{
						context.OperatorStack().push(tempToken);
						context.OperatorStack().push(token);
						break;
					}
					else
					{
						if(AssertHelper::CreateHandlerExists(tempToken->Token,context,TEXT("Unknow operator.")))
						{
							map<ExpressionString,ParseContext::CreateNodeHandlerPtr>::iterator createHandlerIter=ParseContext::createHandlerMap->find(tempToken->Token);
							createHandlerIter->second(context);
							if (context.OperatorStack().size() > 0)
                            {
                                tempToken = context.OperatorStack().top();
								context.OperatorStack().pop();
                            }
                            else
                            {
                                context.OperatorStack().push(token);
                                break;
                            }
						}
						else
						{
							return;
						}
					}
				}
				else
				{
					context.SetError();
					context.SetErrorMsg(TEXT("Unknow operator."));
					return;
				}
			}
		}
		else
		{
			context.OperatorStack().push(token);
		}
	}
}